package br.pucrio.inf.les.SPLAnalyser.impl.squidplugin.query.metricas;

import java.util.ArrayList;
import java.util.List;

import br.ufrn.dimap.ase.squid.core.models.squidmodel.Asset;

public class MetricsCalculator {
	private List<Asset> realImpact = new ArrayList<Asset>();
	private List<Asset> estimatedImpact = new ArrayList<Asset>();
	private List<Asset> falsePositives;
	private List<Asset> falseNegatives;
	private List<Asset> hits;
	
	private float precision;
	private float coverage;
	private float mediaHarmonica;
	
	public MetricsCalculator(List<Asset> realImpact, List<Asset> estimatedImpact) {
		this.realImpact.addAll( realImpact);
		this.estimatedImpact.addAll(estimatedImpact);
		this.falseNegatives = new ArrayList<Asset>();
		this.falsePositives = new ArrayList<Asset>();
		this.hits = new ArrayList<Asset>();
	}
	
	public MetricsCalculator() {
		this.realImpact = new ArrayList<Asset>();
		this.estimatedImpact = new ArrayList<Asset>();
		this.falseNegatives = new ArrayList<Asset>();
		this.falsePositives = new ArrayList<Asset>();
		this.hits = new ArrayList<Asset>();
	}
	
	public void calculate() {
		if(realImpact.size() == 0 || estimatedImpact.size() == 0) {
			System.err.println("Informe o conjunto de impacto real e o conjunto de impacto estimado!");
			return;
		}
		
		for(Asset asset : realImpact) {
			if(estimatedImpact.contains(asset)) {
				hits.add(asset);
			} else {
				falseNegatives.add(asset);
			}
		}
		
		for(Asset asset : estimatedImpact) {
			if(!realImpact.contains(asset)) {
				falsePositives.add(asset);
			}
		}
		
		coverage = (float) hits.size() / (float) realImpact.size();
		precision = (float) hits.size() / (float) estimatedImpact.size();
		mediaHarmonica = (2 * precision * coverage) / (precision + coverage);
	}
	
	public void print() {
		System.out.println("### ACERTOS ###");
		for(Asset asset : hits) {
			System.out.println(asset);
		}
		System.out.println("Total = "+hits.size());
		
		System.out.println("### FALSO POSITIVOS ###");
		for(Asset asset : falsePositives) {
			System.out.println(asset);
		}
		System.out.println("Total = "+falsePositives.size());
		
		System.out.println("### FALSO NEGATIVOS ###");
		for(Asset asset : falseNegatives) {
			System.out.println(asset);
		}
		System.out.println("Total = "+falseNegatives.size());
	}
	
	public float calculateHarmonic(float p, float c) {
		return (2 * p * c) / (p + c);
	}
	
	public float getPrecision() {
		return precision;
	}
	
	public float getCoverage() {
		return coverage;
	}
	
	public float getMediaHarmonica() {
		return mediaHarmonica;
	}

	public List<Asset> getRealImpact() {
		return realImpact;
	}

	public void setRealImpact(List<Asset> realImpact) {
		this.realImpact = realImpact;
	}

	public List<Asset> getEstimatedImpact() {
		return estimatedImpact;
	}

	public void setEstimatedImpact(List<Asset> estimatedImpact) {
		this.estimatedImpact = estimatedImpact;
	}

	public List<Asset> getFalsePositives() {
		return falsePositives;
	}

	public List<Asset> getFalseNegatives() {
		return falseNegatives;
	}

	public List<Asset> getHits() {
		return hits;
	}
	
}
